# !/usr/bin/env python3
# -*- coding: utf-8 -*-

import xml.etree.ElementTree as EleTree
from util.lib import pretty_xml, get_node_type
from util.topo_adapter import get_topo_set


def _init_cb_tbl_xml(tbl_set, index_tbl_xml):
    root = EleTree.Element('eliminate_tbl')
    for entry in tbl_set:
        node_ele = EleTree.SubElement(root, 'node')
        node_id_ele = EleTree.SubElement(node_ele, 'node_id')
        node_id_ele.text = str(entry['node_id'])
        ci = 0
        for flow in entry['flow_set']:
            entry_ele = EleTree.SubElement(node_ele, 'entry')
            flow_id_ele = EleTree.SubElement(entry_ele, 'flow_id')
            flow_id_ele.text = str(flow['flow_id'])
            flow_type_ele = EleTree.SubElement(entry_ele, 'ci')
            flow_type_ele.text = str(ci)
            ci = ci+1
        # root.append(node_ele)
    tree = EleTree.ElementTree(root)
    pretty_xml(root, '\t', '\n')
    tree.write(index_tbl_xml,
               encoding='utf-8',
               xml_declaration=True)
    return


def _update_cb_set(tbl_set, node_type_set):
    """
    转将属于同一节点的索引表整合到一起
    """
    # 将属于同一节点的映射表整合到一起
    node_id_set = []
    for tbl in tbl_set:
        node_id = tbl['node_id']
        if node_id not in node_id_set:
            node_id_set.append(node_id)

    index_tbl_set = [{'node_id': node_id, 'flow_set': []} for node_id in node_id_set]

    for entry in tbl_set:
        node_id = entry['node_id']
        for tbl in index_tbl_set:
            if tbl['node_id'] == node_id:
                del entry['node_id']
                tbl['flow_set'].append(entry)
                break

    last_index_tbl_set = []
    for tbl in index_tbl_set:
        node_id = tbl['node_id']
        for node_type in node_type_set:
            if node_type['node_id'] == node_id and node_type['node_type'] == 1:
                last_index_tbl_set.append(tbl)
    [print(entry) for entry in last_index_tbl_set]
    return last_index_tbl_set


def _get_cb_set(flow_xml, topo_set):
    index_set = []

    # 解析每一条流量
    # 在每一条流量的源节点加上流映射表表项
    tree = EleTree.parse(flow_xml)
    flow_set_ele = tree.findall('flow')
    for flow_ele in flow_set_ele:
        # 判断这条流量是否需要进行复制
        redundant_flag_ele = flow_ele.find("redundant")
        redundant_flag = int(redundant_flag_ele.text)
        if redundant_flag == 0:
            continue

        # 此版本不生成帧消除表
        continue

        # 提取流信息
        entry = {}
        flow_id_ele = flow_ele.find("stream_id")
        flow_id = int(flow_id_ele.text)
        entry.update({'flow_id': flow_id})
        flow_type = flow_ele.findtext('flow_type')
        # 非ST流量不需要注入时刻表
        if flow_type == 'ST':
            flow_type = 0
        elif flow_type == 'AVB':
            flow_type = 1
        entry.update({'flow_type': flow_type})

        # 找到这条流的最后一跳交换机
        route_eles = flow_ele.findall("route")
        last_link_id = int(route_eles[-1].text)

        for topo_entry in topo_set:
            if last_link_id == topo_entry['link_id']:
                entry.update({'node_id': int(topo_entry['dst_node_id'])})
                index_set.append(entry)
                continue

    return index_set


def assemble_cb_tbl(topo_xml, flow_xml, para_xml, cb_tbl_xml):
    # 1.获取linkid与源节点的对应关系
    topo_set = get_topo_set(topo_xml)
    print("1. topo_set: ")
    [print(entry) for entry in topo_set]
    # 2.根据para_xml，获取设备节点的类型，node_type_set
    node_type_set = get_node_type(para_xml)
    print("2. node_type_set: ")
    [print(entry) for entry in node_type_set]

    # 3.获取需要进行帧消除的流信息
    tbl_set = _get_cb_set(flow_xml, topo_set)

    # 4.初始化帧消除表结构体
    cb_tbl = _update_cb_set(tbl_set, node_type_set)
    # 5.生成tbl.xml
    _init_cb_tbl_xml(cb_tbl, cb_tbl_xml)

    return


def main():
    topo_xml = '../input/topo_feature.xml'
    flow_xml = '../input/flow_feature.xml'
    para_xml = '../input/cfg_parameter.xml'
    cb_tbl_xml = '../output/tbl/cb_tbl.xml'
    assemble_cb_tbl(topo_xml, flow_xml, para_xml, cb_tbl_xml)
    return


if __name__ == '__main__':
    main()
